home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / sound / alaw sdec scom / componentdispatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  12.2 KB  |  333 lines

  1. /*
  2.     File:        ComponentDispatch.c
  3.  
  4.     Contains:    Common routines for dispatching for any sound component
  5.  
  6.     Written by: Mark Cookson    
  7.  
  8.     Copyright:    Copyright © 1996-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 8/13/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 
  21.  
  22. */
  23.  
  24. #include "ComponentDispatch.h"
  25. #include <Gestalt.h>
  26. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  27. //    Sound Component Entry Point
  28. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  29.  
  30. #if GENERATINGPOWERPC
  31. ProcInfoType __procinfo=uppSoundComponentEntryPointProcInfo;
  32. #endif
  33. pascal ComponentResult main(ComponentParameters *params, SoundComponentGlobalsPtr globals)
  34. {
  35.     ComponentResult                result;
  36.     short                        selector = params->what;
  37.  
  38.     if (selector < 0)
  39.         switch (selector - kComponentRegisterSelect)    // standard component selectors
  40.         {
  41.             case kComponentRegisterSelect - kComponentRegisterSelect:
  42.                 result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentRegister);
  43.                 break;
  44.  
  45.             case kComponentVersionSelect - kComponentRegisterSelect:
  46.                 return (kSoundComponentVersion);
  47.                 break;
  48.  
  49.             case kComponentCanDoSelect - kComponentRegisterSelect:
  50.                 result = __SoundComponentCanDo(0, *((short *) ¶ms->params[0]));
  51.                 break;
  52.  
  53.             case kComponentCloseSelect - kComponentRegisterSelect:
  54.                 result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentClose);
  55.                 break;
  56.  
  57.             case kComponentOpenSelect - kComponentRegisterSelect:
  58.                 result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentOpen);
  59.                 break;
  60.  
  61.             default:
  62.                 result = badComponentSelector;
  63.                 break;
  64.         }
  65.     else if (selector < kDelegatedSoundComponentSelectors)            // selectors that cannot be delegated
  66.         switch (selector)
  67.         {
  68.             case kSoundComponentSetSourceSelect:
  69.                 result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentSetSource);
  70.                 break;
  71.  
  72.             case kSoundComponentGetSourceDataSelect:
  73.                 result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentGetSourceData);
  74.                 break;
  75.  
  76.             case kSoundComponentSetOutputSelect:
  77.                 result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentSetOutput);
  78.                 break;
  79.  
  80.             default:
  81.                 result = badComponentSelector;
  82.                 break;
  83.         }
  84.     else                                                    // selectors that can be delegated
  85.         switch (selector)
  86.         {
  87.             case kSoundComponentGetInfoSelect:
  88.                 result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentGetInfo);
  89.                 break;
  90.  
  91.             case kSoundComponentStopSourceSelect:
  92.                 result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentStopSource);
  93.                 break;
  94.  
  95.             case kSoundComponentPlaySourceBufferSelect:
  96.                 result = CallComponentFunctionWithStorageUniv((Handle) globals, params, __SoundComponentPlaySourceBuffer);
  97.                 break;
  98.  
  99.             default:
  100.                 result = DelegateComponentCall(params, globals->sourceComponent);
  101.                 break;
  102.         }
  103.  
  104.     return (result);
  105. }
  106.  
  107.  
  108. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  109. static pascal ComponentResult __SoundComponentCanDo(void *unused1, short selector)
  110. {
  111. #pragma unused (unused1)
  112.  
  113.     ComponentResult        result;
  114.  
  115.     switch (selector)
  116.     {
  117.         case kComponentRegisterSelect:
  118.         case kComponentVersionSelect:
  119.         case kComponentCanDoSelect:
  120.         case kComponentCloseSelect:
  121.         case kComponentOpenSelect:
  122.         case kSoundComponentSetSourceSelect:
  123.         case kSoundComponentGetSourceSelect:
  124.         case kSoundComponentGetSourceDataSelect:
  125.         case kSoundComponentSetOutputSelect:
  126.         // selectors that can be delegated
  127.         case kSoundComponentGetInfoSelect:
  128.         case kSoundComponentStopSourceSelect:
  129.         case kSoundComponentPlaySourceBufferSelect:
  130.             result = true;
  131.             break;
  132.  
  133.         default:
  134.             result = false;
  135.             break;
  136.     }
  137.  
  138.     return (result);
  139. }
  140.  
  141. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  142. // Component Manager Methods
  143. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  144. /*    ==============================================================================
  145.     Component Open
  146.  
  147.     This routine is called when the Component Manager creates an instance of this
  148.     component. The routine should allocate global variables in the appropriate heap
  149.     and call SetComponentInstanceStorage() so the Component Manager can remember
  150.     the globals and pass them to all the method calls.
  151.     
  152.     Determining the heap to use can be tricky. The Component Manager will normally
  153.     load the component code into the system heap, which is good, since many applications
  154.     will be sharing this component to play sound. In this case, the components's global
  155.     variable storage should also be created in the system heap.
  156.  
  157.     However, if system heap memory is tight, the Component Manager will load
  158.     the component into the application heap of the first application that plays sound.
  159.     When this happens, the component should create global storage in the application heap
  160.     instead. The Sound Manager will make sure that other applications will not try
  161.     to play sound while the component is in this application heap.
  162.  
  163.     To determine the proper heap to use, call GetComponentInstanceA5(). If the value
  164.     returned is 0, then the component was loaded into the system heap, and all storage
  165.     should be allocated there. If the value returned is non-zero, the component is in
  166.     the application heap specifed by returned A5 value, and all storage should be
  167.     allocated in this application heap.
  168.     
  169.     NOTE: If the component is loaded into the application heap, the value returned by
  170.     GetComponentRefCon() will be 0.
  171.     NOTE: Do not attempt to initialize in this call, since the Component Manager will
  172.     call Open() BEFORE calling Register().
  173.     NOTE: This routine is never called at interrupt time.
  174.     ============================================================================== */
  175.  
  176. pascal ComponentResult __SoundComponentOpen(void *unused1, ComponentInstance self)
  177. {
  178. #pragma unused (unused1)
  179.  
  180.     Handle            h;
  181.     SoundComponentGlobalsPtr        globals;
  182.  
  183.     h = NewHandleClear(sizeof(SoundComponentGlobals));        // get space for globals
  184.     if (h == nil)
  185.         return(MemError());
  186.  
  187.     HLock(h);
  188.     globals = (SoundComponentGlobalsPtr) *h;
  189.     SetComponentInstanceStorage (self, (Handle) globals);     // save pointer to our globals
  190.  
  191.     globals->globalsHandle = h;                                // remember the handle
  192.     globals->thisComponent.format = kOutputSampleFormat;    // output sample format
  193.     globals->thisComponent.sampleSize = kOutputSampleSize;    // output sample size
  194.     globals->outputSamples = kMaxOutputSamples;                // size of our output buffer
  195.  
  196.     return (noErr);
  197. }
  198.  
  199. /*    ==============================================================================
  200.     Component Close
  201.  
  202.     This routine is called when the Component Manager is closing the instance of
  203.     this component. It should delete all global storage and close any other components
  204.     that were opened.
  205.     
  206.     NOTE: Be sure to check that the globals pointer passed in to this routine is
  207.     not set to NIL. If the Open() routine fails for any reason, the Component
  208.     Manager will call this routine passing in a NIL for the globals.
  209.     NOTE: This routine is never called at interrupt time.
  210.     ============================================================================== */
  211.  
  212. pascal ComponentResult __SoundComponentClose(SoundComponentGlobalsPtr globals, ComponentInstance self)
  213. {
  214. #pragma unused (self)
  215.  
  216.     if (globals)                                            // we have some globals
  217.     {
  218.         if (globals->sourceComponent)                        // we have a source component
  219.             CloseComponent(globals->sourceComponent);        // close it
  220.     
  221.         globals->thisComponent.sampleCount = 0;                // nothing in our buffer now
  222.         DisposeHandle(globals->globalsHandle);                // dispose our storage
  223.     }
  224.  
  225.     return (noErr);
  226. }
  227.  
  228. /*    ==============================================================================
  229.     Component Register
  230.  
  231.     This routine is called once, usually at boot time, when the Component Manager
  232.     is first registering this sound component. This routine should check to see if the proper
  233.     Sound Manager is installed and return 0 if it is. If the right Sound Manager is not
  234.     installed, the routine should return 1 and this component will not be registered.
  235.  
  236.     NOTE: The cmpWantsRegisterMessage bit must be set in the component flags of the
  237.     sound component in order for this routine to be called.
  238.     NOTE: This routine is never called at interrupt time.
  239.     ============================================================================== */
  240.  
  241. pascal ComponentResult __SoundComponentRegister(SoundComponentGlobalsPtr globals)
  242. {
  243. #pragma unused (globals)
  244.  
  245.     long        result;
  246.     NumVersion    version;
  247.  
  248.     if ((Gestalt(gestaltSoundAttr, &result) == noErr) &&        // snd gestalt is available
  249.         (result & (1L << gestaltSoundIOMgrPresent)))            // snd dispatcher is available
  250.     {
  251.         version = SndSoundManagerVersion();                        // get the Sound Manager version
  252.         if (version.majorRev >= kRequiredSndMgrMajorRev)        // it's what we need
  253.         {
  254.             return (0);                                            // install this compression component
  255.         }
  256.     }
  257.     
  258.     return (1);                                                    // do not install component
  259. }
  260.  
  261. /*    ==============================================================================
  262.     GetInfo
  263.  
  264.     This routine returns information about this output component to the Sound Manager.
  265.     A 4-byte OSType selector is used to determine the type and size of the information
  266.     to return. If the component does not support a selector, it should delegate this
  267.     call on up the chain.
  268.  
  269.     NOTE: This can be called at interrupt time. However, selectors that return
  270.     a handle will not be called at interrupt time.
  271.     ============================================================================== */
  272.  
  273. pascal ComponentResult __SoundComponentGetInfo(SoundComponentGlobalsPtr globals, SoundSource sourceID,
  274.                                  OSType selector, void *infoPtr)
  275. {
  276.     ComponentResult        result = noErr;
  277.  
  278.     switch (selector)
  279.     {
  280.         case siCompressionFactor:
  281.             GetCompressorInfo(infoPtr);                    // fill out the CompressionInfo structure passed in
  282.             break;
  283.  
  284.         default:
  285.             result = SoundComponentGetInfo(globals->sourceComponent, sourceID, selector, infoPtr);
  286.             break;
  287.     }
  288.  
  289.     return (result);
  290. }
  291.  
  292. /*    ==============================================================================
  293.     StopSource
  294.  
  295.     This routine is used to stop sounds that are currently playing. It should
  296.     clear out any internal buffers, reset any compression state information
  297.     and then delegate the call up the chain.
  298.  
  299.     NOTE: This can be called at interrupt time.
  300.     ============================================================================== */
  301.  
  302. pascal ComponentResult __SoundComponentStopSource(SoundComponentGlobalsPtr globals, short count, SoundSource *sources)
  303. {
  304.     globals->sourceDataPtr = nil;                        // clear out internal buffers
  305.     globals->thisComponent.sampleCount = 0;                // our buffer is empty
  306. #ifdef COMPRESSION
  307.     InitializeCompressor(globals);                        // initialize our compressor state
  308. #else
  309.     InitializeDecompressor(globals);                    // initialize our compressor state
  310. #endif
  311.     return (SoundComponentStopSource(globals->sourceComponent, count, sources));    // delegate this call
  312. }
  313.  
  314. /*    ==============================================================================
  315.     PlaySourceBuffer
  316.  
  317.     This routine is used to start a new sound playing. It should clear out any internal buffers
  318.     but should NOT reset any compression state information, since this could be a
  319.     continuation of a sound that has been broken into pieces. Then the call should be
  320.     delegated up the chain.
  321.  
  322.     NOTE: This can be called at interrupt time.
  323.     ============================================================================== */
  324.  
  325. pascal ComponentResult __SoundComponentPlaySourceBuffer(SoundComponentGlobalsPtr globals, SoundSource sourceID, SoundParamBlockPtr pb, long actions)
  326. {
  327.     globals->sourceDataPtr = nil;                        // clear out internal buffers
  328.     globals->thisComponent.sampleCount = 0;                // our buffer is empty
  329.  
  330.     return (SoundComponentPlaySourceBuffer(globals->sourceComponent, sourceID, pb, actions));    // delegate this call
  331. }
  332.  
  333.